﻿using Infrastructure.Extension;
using Infrastructure.WebApi;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Neoit.Utils;
using System.Threading.Tasks;

namespace Application.Service
{
    public class PassiveService : IPassiveService
    {
        public JobManagerDbContext _context { get; set; }
        private readonly IConfiguration _config;
        private readonly IServiceScopeFactory _scopeFactory;
        private readonly IEmailService _emailService;

        public PassiveService(JobManagerDbContext DbContext, IConfiguration config, IServiceScopeFactory scopeFactory, IEmailService emailService)
        {
            _context = DbContext;
            _config = config;
            _scopeFactory = scopeFactory;
            _emailService = emailService;
        }
        public async Task<Page<Passive>> Get(PassiveListRequest request)
        {
            request.StringTrim();
            var data = await _context.Passive.AsQueryable()
                .WhereIf(request.Key != null, s => s.Key == request.Key)
                .WhereIf(request.Keyword.Has(), s => s.Key.Contains(request.Keyword) || s.Name.Contains(request.Keyword))
                .PageAsync(request.PageIndex, request.PageSize);
            return data;
        }

        public async Task<bool> Add(PassiveForm request)
        {
            await Check(request);
            await _context.Passive.AddAsync(new Passive
            {
                Name = request.Name,
                Key = request.Key,
                Token = SecretHelper.PersonalAccessToken(_config["AESKey"]),
                CallbackValue = request.CallbackValue,
                Notices = request.Notices,
                NoticeObjects = request.NoticeObjects,
            });
            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> Update(PassiveForm request)
        {
            await Check(request);
            var data = await _context.Passive.FirstOrDefaultAsync(s => s.Id == request.Id);
            data.Name = request.Name;
            data.CallbackValue = request.CallbackValue;
            data.UpdateTime = DateTime.Now;
            data.Notices = request.Notices;
            data.NoticeObjects = request.NoticeObjects;
            await _context.SaveChangesAsync();
            return true;
        }

        public async Task Delete(IdRequest request)
        {
            var data = await _context.Passive.FirstOrDefaultAsync(s => s.Id == request.Id);
            data.Delete();
            await _context.SaveChangesAsync();
        }

        public async Task Check(PassiveForm request)
        {
            var data = await _context.Passive.AnyAsync(s => s.Id != request.Id && s.Key == request.Key);
            if (data) BusinessException.Throw("存在重复的Key");
        }

        #region 公开
        public async Task<string> Value(PassiveCallback request)
        {
            if (!SecretHelper.VerifyPersonalAccessToken(request.Token, _config["AESKey"])) BusinessException.Throw("token格式有误");
            var data = await _context.Passive.FirstOrDefaultAsync(s => s.Key == request.Key);
            if (data.Token != request.Token) BusinessException.Throw("token error");

            return data.CallbackValue;
        }
        public async Task<string> Callback(PassiveCallback request)
        {
            if (!SecretHelper.VerifyPersonalAccessToken(request.Token, _config["AESKey"])) BusinessException.Throw("token格式有误");
            var data = await _context.Passive.FirstOrDefaultAsync(s => s.Key == request.Key);
            if (data.Token != request.Token) BusinessException.Throw("token error");
            var originValue = data.CallbackValue;
            data.CallbackValue = request.Value;
            data.CallbackTime = DateTime.Now;
            var notices = data.Notices.ToEntity<List<NoticeInfo>>();
            var notice = notices.FirstOrDefault(s => s.IsEnble && s.TriggerValue == request.Value);
            if (notice != null) SendEmailTask(data.NoticeObjects, notice.Content);
            // add log
            var log = new JobTaskRun
            {
                JobId = data.Id,
                Content = $"[{originValue}] 变更为 [{request.Value}]",
                HasNotice = notice != null,
                IsSuccess = true,
                JobType = JobType.Url,
                Note = notice == null?"": $"通知人员：{data.NoticeObjects}\r\n通知内容：{notice.Content}"
            };
            await _context.JobTaskRun.AddAsync(log);
            await _context.SaveChangesAsync();
            return "Success";
        }

        private async Task AddLog(int taskId,string Content,bool HasNotice)
        {
            var data = new JobTaskRun
            {
                JobId = taskId,
                Content = Content,
                HasNotice = HasNotice,
            };
            await _context.JobTaskRun.AddAsync(data);
        }

        private void SendEmailTask(string tos, string content)
        {
            _ = Task.Run(async () =>
            {
                using (var scope = _scopeFactory.CreateScope())
                {
                    var service = scope.ServiceProvider.GetRequiredService<IEmailService>();
                    await service.Send(new SendEmailInfo
                    {
                        Subject = "Task Change",
                        BodyInfo = content,
                        ToEmails = tos,
                        IsBodyHtml = true,
                    });
                }
            });

        }
        #endregion
    }

    public interface IPassiveService
    {
        Task<Page<Passive>> Get(PassiveListRequest request);
        Task<bool> Add(PassiveForm request);
        Task<bool> Update(PassiveForm request);
        Task Delete(IdRequest request);
        Task<string> Callback(PassiveCallback request);
        Task<string> Value(PassiveCallback request);
    }
}
